package com.kakame.pastime;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AutoGenerateMap {
	
	private static final int MAP_WIDTH = 10;
	private static final int MAP_HEIGHT = 10;
	private static int[][] MAP = new int[MAP_WIDTH + 1][MAP_HEIGHT + 1];
	private static Map<String, List<Point>> WAYS = new HashMap<>();
	
	public static void main(String[] args) {
		generateMap();
		outPutMap();
	}

	/**
	 * 输出地图
	 * @author ex-hejm
	 * @date 2018年12月7日下午5:37:07
	 */
	private static void outPutMap() {
		for (int i = 0; i < MAP.length; i++) {
			for (int j = 0; j < MAP[i].length; j++) {
				System.out.print(MAP[i][j]);
			}
			System.out.println();
		}
		System.out.println("===============");
	}

	private static void generateMap() {
		for (int i = 0; i < MAP.length; i++) {
			for (int j = 0; j < MAP[i].length; j++) {
				MAP[i][j] = 1;
			}
		}
		
		Random rand = new Random();
		
		int outNum = rand.nextInt(7) + 2;  // 出口数，至少应该有两个，最多8个
		List<Point> outPoints = new ArrayList<>(outNum);
		// 生成出口点
		for(int i = 0; i < outNum; i++) {
			outPoints.add(generateOut(outPoints));
		}
		
		System.out.println(outPoints);
		
		for (Point p : outPoints) {
			MAP[p.x][p.y] = 0;
		}
		
		outPutMap();
		
		for (Point point : outPoints) {
			List<Point> ops = new ArrayList<>();
			ops.add(point);
			WAYS.put(point.x + "_" + point.y, ops);
		}
		
		ExecutorService exe = Executors.newFixedThreadPool(outPoints.size());
		for (Point point : outPoints) {
			exe.execute(new Runnable() {
				@Override
				public void run() {
					WAYS.put(point.x + "_" + point.y, generateWay(point, null));
				}
			});
		}
		exe.shutdown();
		while (true) {  
            if (exe.isTerminated()) {  
                System.out.println("结束了！"); 
                
                Iterator<Entry<String, List<Point>>> iterator = WAYS.entrySet().iterator();
        		while (iterator.hasNext()) {
        			Map.Entry<String, List<Point>> entry = iterator.next();
        			List<Point> value = entry.getValue();
        			System.out.println(value);
        			for (Point p : value) {
        				MAP[p.x][p.y] = 0;
        			}
        		}
        		
                break;  
            }  
            try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}  
        } 
	}

	/**
	 * 生成路线
	 * @author ex-hejm
	 * @date 2018年12月7日下午4:13:35
	 * @param point
	 * @return 
	 */
	private static List<Point> generateWay(Point srcPoint, Point spoint) {
		Point point = new AutoGenerateMap().new Point(); 
		if(null != spoint) {
			point.x = spoint.x;
			point.y = spoint.y;
		}
		Random rand = new Random();
		int dire = rand.nextInt(4);  // 随机走一个方向
		if(dire == 0) {  // 向上走，x不变，y-1
			int y = point.y - 1;
			if(y < 0) {
				return generateWay(srcPoint, point);
			} else {
				point.y = y;
			}
		} else if(dire == 1) {  // 向右走，x+1，y不变
			int x = point.x + 1;
			if(x > MAP_WIDTH) {
				return generateWay(srcPoint, point);
			} else {
				point.x = x;
			}
		} else if(dire == 2) {  // 向下走，x不变，y+1
			int y = point.y + 1;
			if(y > MAP_HEIGHT) {
				return generateWay(srcPoint, point);
			} else {
				point.y = y;
			}
		} else if(dire == 3) {  // 向左走，x-1，y不变
			int x = point.x - 1;
			if(x < 0) {
				return generateWay(srcPoint, point);
			} else {
				point.x = x;
			}
		}
		
		// 只要这个点与其他线上延伸出来的点相交了，就退出
		Iterator<Entry<String, List<Point>>> iterator = WAYS.entrySet().iterator();
		
		List<Point> ownWay = WAYS.get(srcPoint.x + "_" + srcPoint.y);  // 自己的路
		synchronized (ownWay) {
			if(ownWay == null) {
				ownWay = new ArrayList<>();
			}
			// 判断有没有相交
			boolean intersectFlsg = false;
			while (iterator.hasNext()) {
				Map.Entry<String, List<Point>> entry = iterator.next();
				String key = entry.getKey();

				if((srcPoint.x + "_" + srcPoint.y).equals(key)) {  // 不要找自己的
					continue;
				}
				
				List<Point> value = entry.getValue();  // 已经走了的路
				for (Point p : value) {
					if(p.x == point.x && p.y == point.y) {
						intersectFlsg = true;
					}
				}
				if(intersectFlsg) {  // 相交了
					break;
				}
			}
			if(intersectFlsg) {  // 相交了，这条线就不能再走了
				return ownWay;
			} else {
				ownWay.add(point);  // 加入刚走的路
				return generateWay(srcPoint, point);
			}
		}
	}

	/**
	 * 生成出口
	 * @author ex-hejm
	 * @return 
	 * @date 2018年12月7日下午3:58:46
	 */
	private static Point generateOut(List<Point> existPoints) {
		Point point = new AutoGenerateMap().new Point();
		
		Random rand = new Random();
		int dire = rand.nextInt(4);  // 出口所在的边，0 上 1 右 2 下 3 左
		point.d = dire;
		if(dire == 0) {  // 在上边，就只生成x即可，y=0
			point.x = rand.nextInt(MAP_WIDTH);
			point.y = 0;
		} else if(dire == 1) {  // 在右边，就只生成y即可，x=width
			point.x = MAP_WIDTH;
			point.y = rand.nextInt(MAP_HEIGHT);
		} else if(dire == 2) {  // 在下边，就只生成x即可，y=height
			point.x = rand.nextInt(MAP_WIDTH);
			point.y = MAP_HEIGHT;
		} else if(dire == 3) {  // 在左边，就只生成y即可，x=0
			point.x = 0;
			point.y = rand.nextInt(MAP_HEIGHT);
		}
		boolean existFlag = false;
		for(Point e : existPoints) {
			if(e.x == point.x && e.y == point.y) {  // 已经有这个点了，就重新生成
				existFlag = true;
			}
		}
		if(!existFlag) {
			return point;
		} else {
			return generateOut(existPoints);
		}
	}

	class Point {
		int x;
		int y;
		int d;
		
		@Override
		public String toString() {
			return "(" + x + ", " + y + ", " + getDirect() + ")";
		}
		
		public String getDirect() {
			if(d == 0) {
				return "上";
			} else if(d == 1) {
				return "右";
			} else if(d == 2) {
				return "下";
			} else if(d == 3) {
				return "左";
			}
			return d + "";
		}
	}
	
}
